﻿using AutoMapper;
using HamcoWcs.Contract;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractMes;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.PalletInfos;
using HamcoWcs.Entitys.WcsLocations;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.Exceptions;
using HamcoWcs.Models.ForeEndModels.Wms;
using HamcoWcs.Models.MainTasks;
using HamcoWcs.Models.TibcoMessage;
using HamcoWcs.Models.TibcoMessage.Items;
using HamcoWcs.Models.WcsLocations;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;

namespace HamcoWcs.Service.Common
{
    [AutoInject(typeof(ILocationService), InjectType.Scope)]
    public class LocationService : ScopeServiceBase, ILocationService
    {
        private readonly AutomaticStorageInfo _asrs;
        private readonly ILoggerService _logger;
        private readonly IMesCommunicateService _mesCommunicateService;
        public LocationService(AutomaticStorageInfo asrs, ILoggerService logger, IMesCommunicateService mesCommunicateService, WcsDbContext wcsDbContext, IMapper mapper) : base(wcsDbContext, mapper)
        {
            _asrs = asrs;
            _logger = logger;
            _mesCommunicateService = mesCommunicateService;
            if (SRM_STATION_PCONNAME == null || SRM_STATION_PCONNAME.Count == 0)
            {
                SRM_STATION_PCONNAME = new Dictionary<string, int>();
                var stations = _wcsDbContext.WcsLocations.Where(x => x.LocType == "station").ToList();

                foreach (var item in stations)
                {
                    if (!SRM_STATION_PCONNAME.ContainsKey(item.WmsLocName))
                    {
                        SRM_STATION_PCONNAME.Add(item.WmsLocName, int.Parse(item.SrmName));
                    }
                }
            }
        }

        private static Dictionary<string, int> SRM_STATION_PCONNAME;

        private static Dictionary<string, Dictionary<int, EnumWcsShelfZone>> DIC_BAY_ZONE = new Dictionary<string, Dictionary<int, EnumWcsShelfZone>>();
        private static Dictionary<string, TempHandOffBay> DIC_MID_BAY = new Dictionary<string, TempHandOffBay>();
        private static Dictionary<string, ShelfInfoDto> INVENTORY_SHELF_INFO;

        public Dictionary<string, ShelfInfoDto> GetInventoryShelfInfo()
        {

            if (INVENTORY_SHELF_INFO == null || INVENTORY_SHELF_INFO.Count == 0)
            {
                INVENTORY_SHELF_INFO = _wcsDbContext.WcsLocations.AsNoTracking().Where(x => x.LocType == "shelf")
                    .OrderBy(x => x.Bay).ThenBy(x => x.Lev)
                    .Select(x => new ShelfInfoDto()
                    {
                        Aisle = x.Aisle,
                        Bay = x.Bay,
                        Row = x.Row,
                        Lev = x.Lev,
                        WcsLocName = x.WcsLocName,
                    }).ToDictionary(k => k.WcsLocName, v => v);
            }

            return INVENTORY_SHELF_INFO;
        }

        public List<LocationCascaderDto> GetLocationCascader()
        {
            var locCascader = new List<LocationCascaderDto>();

            try
            {
                var locs = _wcsDbContext
                    .WcsLocations
                    .AsNoTracking()
                    .Where(x => x.LocType == "shelf")
                    .Where(x => !x.ZoneName.Contains("Z6"))
                    .ToList();

                var rows = locs.Select(x => x.Row).Distinct().ToList();

                foreach (var row in rows)
                {
                    var cols = locs.Where(x => x.Row == row)
                                   .Select(x => x.Bay)
                                   .Distinct()
                                   .ToList();

                    var loc = new LocationCascaderDto(row.ToString("00"), $"第{row}排", new List<LocationCascaderDto>());
                    foreach (var col in cols)
                    {
                        var levs = locs.Where(x => x.Row == row)
                                       .Where(x => x.Bay == col)
                                       .Select(x => new { x.Lev, x.LocStatus })
                                       .Distinct()
                                       .ToList();

                        var colLoc = new LocationCascaderDto($"{row:00}{col:000}", $"第{col}列", new List<LocationCascaderDto>());

                        foreach (var lev in levs)
                        {
                            var l = new LocationCascaderDto($"{row:00}{col:000}{lev.Lev:00}", $"第{lev.Lev}层");
                            l.LocStatus = lev.LocStatus;
                            colLoc.Children.Add(l);
                        }

                        loc.Children.Add(colLoc);
                    }

                    locCascader.Add(loc);
                }

                return locCascader;
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        public WcsLocation GetEmptyLocationByZone(string zoneName)
        {
            zoneName = zoneName.ToUpper();
            // 优先选择ShareZone区域的货架，降低堆垛机负载率
            var loc = _wcsDbContext.WcsLocations
                                   .AsQueryable()
                                   .Where(x => x.LocType == "shelf")
                                   .Where(d => d.ZoneName == zoneName)
                                   .Where(d => d.LocStatus == (int)EnumLocStatus.Empty)
                                   .Where(d => !d.IsLock && !d.SrmOccupyFlag)
                                   .Where(d => d.WcsZone == EnumWcsShelfZone.ShareZone.ToString())
                                   //.Where(d => !d.BasicShelf)
                                   .OrderBy(d => d.Lev) // 从下网上
                                   .FirstOrDefault();

            if (loc == null)
            {
                loc = _wcsDbContext.WcsLocations
                                   .AsQueryable()
                                   .Where(x => x.LocType == "shelf")
                                   .Where(d => d.ZoneName == zoneName)
                                   .Where(d => d.LocStatus == (int)EnumLocStatus.Empty)
                                   .Where(d => !d.IsLock && !d.SrmOccupyFlag)
                                   .OrderBy(d => d.Lev)
                                   .FirstOrDefault();
            }

            return loc;
        }
        public WcsLocationDto GetEmptyLocation(string zoneName)
        {
            zoneName = zoneName.ToUpper();
            // 优先选择ShareZone区域的货架，降低堆垛机负载率
            var loc = _wcsDbContext.WcsLocations
                                   .AsQueryable()
                                   .Where(x => x.LocType == "shelf")
                                   .Where(d => d.ZoneName == zoneName)
                                   .Where(d => d.LocStatus == (int)EnumLocStatus.Empty)
                                   .Where(d => !d.IsLock && !d.SrmOccupyFlag)
                                   .Where(d => d.WcsZone == EnumWcsShelfZone.ShareZone.ToString())
                                   //.Where(d => !d.BasicShelf)
                                   .OrderBy(d => d.Lev) // 从下网上
                                   .FirstOrDefault();

            if (loc == null)
            {
                loc = _wcsDbContext.WcsLocations
                                   .AsQueryable()
                                   .Where(x => x.LocType == "shelf")
                                   .Where(d => d.ZoneName == zoneName)
                                   .Where(d => d.LocStatus == (int)EnumLocStatus.Empty)
                                   .Where(d => !d.IsLock && !d.SrmOccupyFlag)
                                   .OrderBy(d => d.Lev)
                                   .FirstOrDefault();
            }



            if (loc != null)
            {
                loc.LocStatus = (int)EnumLocStatus.In;
            }

            return _mapper.Map<WcsLocationDto>(loc);
        }

        public WcsLocation GetEmptyLocationBySrm(string srmName)
        {
            var locQuery = _wcsDbContext.WcsLocations
                                   .AsQueryable()
                                   .Where(x => x.LocType == "shelf")
                                   .Where(d => d.LocStatus == (int)EnumLocStatus.Empty)
                                   .Where(d => !d.IsLock && !d.SrmOccupyFlag);

            if (srmName == "Srm01")
            {
                locQuery = locQuery.Where(x => x.Aisle == "CJSTW100")
                    .Where(x => x.WcsZone == EnumWcsShelfZone.OnlyZone1.ToString()
                             || x.WcsZone == EnumWcsShelfZone.UseZone1.ToString()
                             || x.WcsZone == EnumWcsShelfZone.ShareZone.ToString());
            }
            if (srmName == "Srm02")
            {
                locQuery = locQuery.Where(x => x.Aisle == "CJSTW100")
                 .Where(x => x.WcsZone == EnumWcsShelfZone.OnlyZone2.ToString()
                          || x.WcsZone == EnumWcsShelfZone.UseZone2.ToString()
                          || x.WcsZone == EnumWcsShelfZone.ShareZone.ToString());
            }
            if (srmName == "Srm03")
            {
                locQuery = locQuery.Where(x => x.Aisle == "CJSTW200")
                 .Where(x => x.WcsZone == EnumWcsShelfZone.OnlyZone1.ToString()
                          || x.WcsZone == EnumWcsShelfZone.UseZone1.ToString()
                          || x.WcsZone == EnumWcsShelfZone.ShareZone.ToString());
            }
            if (srmName == "Srm04")
            {
                locQuery = locQuery.Where(x => x.Aisle == "CJSTW200")
                .Where(x => x.WcsZone == EnumWcsShelfZone.OnlyZone2.ToString()
                        || x.WcsZone == EnumWcsShelfZone.UseZone2.ToString()
                        || x.WcsZone == EnumWcsShelfZone.ShareZone.ToString());
            }

            var loc = locQuery.OrderBy(d => d.Lev).FirstOrDefault();
            return loc;
        }

        public WcsLocation GetMiddleLocation(string aisle)
        {
            var loc = _wcsDbContext.WcsLocations
                                   .AsQueryable()
                                   .Where(d => d.LocStatus == (int)EnumLocStatus.HandOff)
                                   .Where(x => x.LocType == "shelf")
                                   .Where(d => d.Aisle == aisle)
                                   .Where(d => !d.IsLock && !d.SrmOccupyFlag)
                                   .FirstOrDefault();

            if (loc == null)
            {
                TempHandOffBay midbay;

                if (DIC_MID_BAY.ContainsKey(aisle))
                {
                    midbay = DIC_MID_BAY[aisle];
                }
                else
                {
                    var handoffbays = _wcsDbContext.WcsLocations
                        .Where(x => x.Aisle == aisle)
                        .Where(x => x.ZoneName.Contains("Z6"))
                        //.Where(x => x.LocStatus == (int)EnumLocStatus.HandOff)
                        .Select(x => x.Bay)
                        .Distinct()
                        .ToList();

                    midbay = new TempHandOffBay()
                    {
                        LeftBay = handoffbays.Min() - 1,
                        RightBay = handoffbays.Max() + 1
                    };
                }

                // 空的，没锁定，中转储位两边，
                loc = _wcsDbContext.WcsLocations
                    .Where(x => x.Aisle == aisle)
                    .Where(x => x.LocType == "shelf")
                    .Where(x => x.Bay == midbay.LeftBay || x.Bay == midbay.RightBay)
                    .Where(x => x.LocStatus == 0)
                    .Where(x => !x.IsLock && !x.SrmOccupyFlag)
                    .FirstOrDefault();
            }

            return loc;
        }

        public Dictionary<string, List<Zone>> InventoryZonesByAisle()
        {
            var dic = new Dictionary<string, List<Zone>>();
            var locs = _wcsDbContext.WcsLocations.AsNoTracking().Where(x => x.LocType == "shelf").ToList();
            var aisles = locs.Select(x => x.Aisle).Distinct().ToList();

            foreach (var aisle in aisles)
            {
                var zoneNames = locs.Where(x => x.Aisle == aisle).Select(x => x.ZoneName).Distinct().OrderBy(x => x).ToList();
                var zoneList = new List<Zone>();
                foreach (var zoneName in zoneNames)
                {
                    if (zoneName.Contains("Z6")) continue;

                    var zoneLocs = locs.Where(x => x.ZoneName == zoneName).ToList();
                    int total = zoneLocs.Count;
                    int usedCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.Store).Count();
                    // 非周转货位
                    int emptyCount = zoneLocs.Where(d => !d.IsLock && !d.SrmOccupyFlag
                                                  && d.LocStatus == (int)EnumLocStatus.Empty)
                                                  .Count();
                    int blockCount = zoneLocs.Where(d => d.IsLock || d.SrmOccupyFlag).Count();

                    int reserveCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.In).Count();

                    zoneList.Add(new Zone()
                    {
                        ZoneName = zoneName,
                        TotalCapacity = total,
                        //UsedShelfCount = zoneLocs.Where(d => !string.IsNullOrEmpty(d.UnitId)).Count(),
                        UsedShelfCount = usedCount,
                        EmptyShelfCount = emptyCount,
                        BlockedEmptyShelfCount = blockCount,
                        ReserveShelfCount = reserveCount,
                    });
                }

                dic.Add(aisle, zoneList);
            }
            return dic;
        }

        public List<Zone> InventoryZones()
        {
            var locs = _wcsDbContext.WcsLocations.AsNoTracking().Where(x => x.LocType == "shelf").ToList();
            var zoneNames = locs.Where(x => x.LocType == "shelf").Select(x => x.ZoneName).Distinct().OrderBy(x => x).ToList();
            var zoneList = new List<Zone>();
            foreach (var zoneName in zoneNames)
            {
                if (zoneName.Contains("Z6")) continue;
                var zoneLocs = locs.Where(x => x.ZoneName == zoneName).ToList();
                int total = zoneLocs.Count;
                int usedCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.Store).Count();
                // 非周转货位
                int emptyCount = zoneLocs.Where(d => !d.IsLock && !d.SrmOccupyFlag
                                              && d.LocStatus == (int)EnumLocStatus.Empty)
                                              .Count();
                int blockCount = zoneLocs.Where(d => d.IsLock || d.SrmOccupyFlag).Count();

                int reserveCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.In || d.LocStatus == (int)EnumLocStatus.Out).Count();

                zoneList.Add(new Zone()
                {
                    ZoneName = zoneName,
                    TotalCapacity = total,
                    //UsedShelfCount = zoneLocs.Where(d => !string.IsNullOrEmpty(d.UnitId)).Count(),
                    UsedShelfCount = usedCount,
                    EmptyShelfCount = emptyCount,
                    BlockedEmptyShelfCount = blockCount,
                    ReserveShelfCount = reserveCount,
                });
            }
            return zoneList;
        }

        public List<Zone> InventoryZonesByZone(string zoneName)
        {
            var zoneList = new List<Zone>();

            var zoneLocs = _wcsDbContext.WcsLocations.AsNoTracking()
                .Where(x => x.LocType == "shelf")
                .Where(d => d.ZoneName == zoneName).ToList();
            int total = zoneLocs.Count;
            int usedCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.Store).Count();
            // 非周转货位
            int emptyCount = zoneLocs.Where(d => !d.IsLock && !d.SrmOccupyFlag
                                          && d.LocStatus == (int)EnumLocStatus.Empty)
                                          .Count();
            int blockCount = zoneLocs.Where(d => d.IsLock || d.SrmOccupyFlag).Count();

            int reserveCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.In).Count();

            zoneList.Add(new Zone()
            {
                ZoneName = zoneName,
                TotalCapacity = total,
                UsedShelfCount = usedCount,
                EmptyShelfCount = emptyCount,
                BlockedEmptyShelfCount = blockCount,
                ReserveShelfCount = reserveCount,
            });

            return zoneList;
        }

        public List<Pallet> InventoryPallets()
        {
            var pallets = _wcsDbContext.WcsLocations
                                    //.Where(x => !string.IsNullOrEmpty(x.UnitId))
                                    .AsNoTracking()
                                    .Where(x => x.LocType == "shelf")
                                    .Select(x => new Pallet()
                                    {
                                        PalletName = x.UnitId,
                                        CurrentPositionName = x.WcsLocName,
                                        CurrentPositionType = "SHELF",
                                        PalletLocState = (x.IsLock || x.SrmOccupyFlag) ? "BLOCKED" : "UNBLOCKED",
                                        CurrentZoneName = x.ZoneName,
                                        TransferState = "INSTK"
                                    })
                                    .ToList();
            return pallets;
        }

        public Dictionary<string, List<Pallet>> InventoryPalletsByZone()
        {

            var zones = _wcsDbContext.WcsLocations
                                     .Where(x => x.LocType == "shelf")
                                     .Select(x => x.ZoneName)
                                     .Distinct()
                                     .OrderBy(x => x)
                                     .ToList();

            var zonePallets = new Dictionary<string, List<Pallet>>();

            foreach (var zone in zones)
            {
                zonePallets.Add(zone, _wcsDbContext.WcsLocations
                                    .AsNoTracking()
                                    .Where(x => x.LocType == "shelf")
                                    .Where(x => x.ZoneName == zone)
                                    //.Where(x => x.LocStatus == EnumLocStatus)
                                    .Where(x => !string.IsNullOrEmpty(x.UnitId))
                                    //.Where(x=>!string.IsNullOrEmpty(x.UnitId))
                                    .Select(x => new Pallet()
                                    {
                                        PalletName = x.UnitId,
                                        CurrentPositionName = x.WcsLocName,
                                        CurrentPositionType = "SHELF",
                                        PalletLocState = (x.IsLock || x.SrmOccupyFlag) ? "BLOCKED" : "UNBLOCKED",
                                        CurrentZoneName = x.ZoneName,
                                        TransferState = "INSTK"
                                    })
                                    .ToList());
            }

            return zonePallets;
        }

        public WcsLocation GetPalletLocation(string unitId)
        {
            var loc = _wcsDbContext.WcsLocations
                                    .AsQueryable()
                                    .Where(x => x.LocType == "shelf")
                                    .Where(d => d.UnitId == unitId)
                                    .FirstOrDefault();
            //if (loc != null)
            //    loc.LocStatus = (int)EnumLocStatus.Out;
            return loc;
        }



        public ForeEndResult GetAllLocInfo()
        {
            var sizeDic = new Dictionary<string, int>();
            var queryable = _wcsDbContext.WcsLocations.Where(x => x.LocType == "shelf").ToList();
            var data = _mapper.Map<List<UILocInfo>>(queryable);

            var dic = _wcsDbContext.Set<PalletInfo>().AsNoTracking().ToDictionary(k => k.UnitId, v => v);
            foreach (var loc in data)
            {
                if (string.IsNullOrEmpty(loc.UnitId)) continue;

                if (dic.ContainsKey(loc.UnitId))
                {
                    var p = dic[loc.UnitId];
                    loc.Size = string.IsNullOrEmpty(p.Size) ? "0" : p.Size;
                    loc.PalletType = string.IsNullOrEmpty(p.PalletType) ? "" : p.PalletType;
                    try
                    {
                        if (!p.MaterialInfo.IsNullOrEmpty())
                        {
                            var materialInfo = JsonConvert.DeserializeObject<MaterialInfo>(p.MaterialInfo);
                            if (materialInfo.MaterialCount <= 5 && !loc.PalletType.StartsWith("EMPTY"))
                            {
                                loc.PalletType = "FULL";
                            }
                            if (materialInfo.MaterialCount == 0)
                            {
                                loc.PalletType = "PALLET";
                            }
                        }
                    }
                    catch { }

                }
            }



            return new ForeEndResult(data);
        }

        public MachineAddressDto GetMachineAddress(string fromName)
        {
            var loc = _wcsDbContext.WcsLocations.AsNoTracking()
                .Where(x => x.LocType == "shelf")
                .FirstOrDefault(x => x.WcsLocName == fromName);

            if (loc == null) return null;

            return new MachineAddressDto("CJSTW100", fromName, "SHELF", loc.ZoneName);
        }

        public WcsLocation GetLocationByWcsName(string wcsName)
        => _wcsDbContext.WcsLocations
                .Where(x => x.LocType == "shelf")
                .Where(x => x.WcsLocName == wcsName)
                .FirstOrDefault();


        public WcsLocationDto GetLocationByWmsName(string wmsName, string aisle)
        {
            var loc = _wcsDbContext.WcsLocations
                                   .AsNoTracking()
                                   .Where(x => x.WmsLocName == wmsName)
                                   .Where(x => x.Aisle == aisle)
                                   .FirstOrDefault();
            if (loc == null)
            {
                loc = _wcsDbContext.WcsLocations
                                    .AsNoTracking()
                                    .Where(x => x.WcsLocName == wmsName)
                                    .Where(x => x.Aisle == aisle)
                                    .FirstOrDefault();
            }

            return _mapper.Map<WcsLocationDto>(loc);
        }

        public List<Pallet> GetZonePallets(string zoneName)
        {
            return _wcsDbContext.WcsLocations
                                .AsNoTracking()
                                .Where(x => x.LocType == "shelf")
                                .Where(x => x.ZoneName == zoneName)
                                .Where(x => !string.IsNullOrEmpty(x.UnitId))
                                .Select(x => new Pallet()
                                {
                                    PalletName = x.UnitId,
                                    PalletLocState = (x.IsLock || x.SrmOccupyFlag) ? "BLOCKED" : "UNBLOCKED",
                                    TransferState = "INSTK"
                                })
                                .ToList();
        }

        public List<WcsLocation> GetAllLoc()
        {
            return _wcsDbContext.WcsLocations
                                .AsNoTracking()
                                .Where(x => x.LocType == "shelf")
                                .ToList();
        }

        public bool CheckIsNeedSection(string fromWmsName, string toWmsName, string aisle, out WcsLocationDto floc, out WcsLocationDto tloc)
        {
            floc = GetLocationByWmsName(fromWmsName, aisle);
            tloc = GetLocationByWmsName(toWmsName, aisle);

            try
            {
                var fromZone = floc.WcsZone;
                var toZone = tloc.WcsZone;

                if (fromZone == EnumWcsShelfZone.None || toZone == EnumWcsShelfZone.None)
                    throw new Exception("");

                if ((fromZone == EnumWcsShelfZone.OnlyZone1
                    || fromZone == EnumWcsShelfZone.UseZone1)
                    && (toZone == EnumWcsShelfZone.OnlyZone2
                    || toZone == EnumWcsShelfZone.UseZone2))
                {
                    return true;
                }

                if ((toZone == EnumWcsShelfZone.OnlyZone1
                    || toZone == EnumWcsShelfZone.UseZone1)
                    && (fromZone == EnumWcsShelfZone.OnlyZone2
                    || fromZone == EnumWcsShelfZone.UseZone2))
                {
                    return true;
                }

                return false;
            }
            catch (Exception)
            {
                throw new Exception("判断是否需要分段执行任务失败");
            }
        }

        public EnumWcsShelfZone GetWcsZoneByBay(int bay, string aisle)
        {
            if (DIC_BAY_ZONE == null || DIC_BAY_ZONE.Count == 0)
            {
                var aisles = _wcsDbContext.WcsLocations.AsNoTracking().Select(x => x.Aisle).Distinct().ToList();
                foreach (var a in aisles)
                {
                    var dic = _wcsDbContext.WcsLocations
                        .Where(x => x.Aisle == aisle)
                        .Where(x => x.Row == 2 || x.Row == 4)
                        .Where(x => x.Lev == 2)
                        .ToDictionary(k => k.Bay, v => Enum.Parse<EnumWcsShelfZone>(v.WcsZone));

                    DIC_BAY_ZONE.Add(a, dic);
                }
            }

            return DIC_BAY_ZONE[aisle][bay];
        }

        public int GetPconNameByWmsLocationName(string wmsName)
        {
            if (SRM_STATION_PCONNAME.ContainsKey(wmsName))
            {
                return SRM_STATION_PCONNAME[wmsName];
            }
            else
            {
                return 0;
            }
        }



        public void SrmOccupy(string srmName)
        {
            List<WcsLocation> locs;
            string aisle = "";
            string wcsZone = "";
            string zoneName = "";
            if (srmName.Equals("Srm01", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW100";
                wcsZone = EnumWcsShelfZone.OnlyZone1.ToString();
                zoneName = "CJSTW100Z1";

            }
            else if (srmName.Equals("Srm02", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW100";
                wcsZone = EnumWcsShelfZone.OnlyZone2.ToString();
                zoneName = "CJSTW100Z5";
            }
            else if (srmName.Equals("Srm03", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW200";
                wcsZone = EnumWcsShelfZone.OnlyZone1.ToString();
                zoneName = "CJSTW200Z1";
            }
            else if (srmName.Equals("Srm04", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW200";
                wcsZone = EnumWcsShelfZone.OnlyZone2.ToString();
                zoneName = "CJSTW200Z5";
            }
            else
            {
                throw new Exception($"非法的堆垛机名{srmName}");
            }


            locs = _wcsDbContext.Set<WcsLocation>()
                .Where(x => x.LocType == "shelf")
                .Where(x => x.Aisle == aisle)
                .Where(X => X.WcsZone == wcsZone)
                .ToList();

            if (locs.Count == 0) return;

            foreach (var loc in locs)
            {
                loc.SrmOccupyFlag = true;
            }
            _wcsDbContext.SaveChanges();


            InventoryZone(zoneName);
            InventoryPallet(zoneName);

            //if (locs.Any(x => !string.IsNullOrEmpty(x.UnitId)))
            //{
            //    var pallets = locs.Where(x => !string.IsNullOrEmpty(x.UnitId))
            //        .Where(x => x.UnitId.Length == 6)
            //        .Select(x => new Pallet()
            //        {
            //            PalletName = x.UnitId,
            //            CurrentPositionName = x.WcsLocName,
            //            CurrentPositionType = "SHELF",
            //            CurrentZoneName = x.ZoneName,
            //            PalletLocState = "BLOCKED",
            //            TransferState = "INSTK"
            //        })
            //    .ToList();

            //    var body = new InventoryPalletDataReportMessageBody(aisle, pallets);
            //    _mesCommunicateService.InventoryPalletDataRequest(new InventoryPalletDataReportMessage(body));
            //}
        }


        public void SrmUnoccupy(string srmName)
        {
            List<WcsLocation> locs;
            string aisle = "";
            string wcsZone = "";
            string zoneName = "";
            if (srmName.Equals("Srm01", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW100";
                wcsZone = EnumWcsShelfZone.OnlyZone1.ToString();
                zoneName = "CJSTW100Z1";

            }
            else if (srmName.Equals("Srm02", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW100";
                wcsZone = EnumWcsShelfZone.OnlyZone2.ToString();
                zoneName = "CJSTW100Z5";
            }
            else if (srmName.Equals("Srm03", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW200";
                wcsZone = EnumWcsShelfZone.OnlyZone1.ToString();
                zoneName = "CJSTW200Z1";
            }
            else if (srmName.Equals("Srm04", StringComparison.OrdinalIgnoreCase))
            {
                aisle = "CJSTW200";
                wcsZone = EnumWcsShelfZone.OnlyZone2.ToString();
                zoneName = "CJSTW200Z5";
            }
            else
            {
                throw new Exception($"非法的堆垛机名{srmName}");
            }


            locs = _wcsDbContext.Set<WcsLocation>()
                .Where(x => x.LocType == "shelf")
                .Where(x => x.Aisle == aisle)
                .Where(X => X.WcsZone == wcsZone)
                .ToList();

            if (locs.Count == 0) return;

            foreach (var loc in locs)
            {
                loc.SrmOccupyFlag = false;
            }
            _wcsDbContext.SaveChanges();


            InventoryZone(zoneName);
            InventoryPallet(zoneName);

            //if (locs.Any(x => !string.IsNullOrEmpty(x.UnitId)))
            //{
            //    var pallets = locs.Where(x => !string.IsNullOrEmpty(x.UnitId))
            //        .Where(x => x.UnitId.Length == 6)
            //        .Select(x => new Pallet()
            //        {
            //            PalletName = x.UnitId,
            //            CurrentPositionName = x.WcsLocName,
            //            CurrentPositionType = "SHELF",
            //            CurrentZoneName = x.ZoneName,
            //            PalletLocState = "BLOCKED",
            //            TransferState = "INSTK"
            //        })
            //    .ToList();

            //    var body = new InventoryPalletDataReportMessageBody(aisle, pallets);
            //    _mesCommunicateService.InventoryPalletDataRequest(new InventoryPalletDataReportMessage(body));
            //}
        }


        public void ShelfBlock(string shelfName, string user, string remark = "")
        {
            var loc = _wcsDbContext.Set<WcsLocation>().FirstOrDefault(x => x.WcsLocName == shelfName)
                ?? throw new Exception($"未找到货位{shelfName}");

            if (loc.IsLock) return;

            loc.IsLock = true;

            if (!string.IsNullOrEmpty(remark))
            {
                remark = $"[{DateTime.Now:yyyy-MM-dd HH:m:ss}][{user}]{remark}";
            }

            loc.Remark = remark;
            _wcsDbContext.SaveChanges();
            _mesCommunicateService.PalletLocStateChanged(loc);
            InventoryZone(loc.ZoneName);
            //InventoryPallet(loc.ZoneName);
        }

        public void ShelfUnBlock(string shelfName, string user)
        {
            throw new NotImplementedException();
        }

        public void UpdateShelfRemark(string shelfName, string user, string remark)
        {
            throw new NotImplementedException();
        }

        public void InventoryZone(string zoneName)
        {
            var zoneList = new List<Zone>();

            var zoneLocs = _wcsDbContext.WcsLocations.AsNoTracking()
                .Where(x => x.LocType == "shelf")
                .Where(d => d.ZoneName == zoneName)
                .ToList();

            int usedCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.Store).Count();

            int emptyCount = zoneLocs.Where(d => !d.IsLock && !d.SrmOccupyFlag
                                          && d.LocStatus == (int)EnumLocStatus.Empty)
                                          .Count();
            int blockCount = zoneLocs.Where(d => d.IsLock || d.SrmOccupyFlag).Count();

            int reserveCount = zoneLocs.Where(d => d.LocStatus == (int)EnumLocStatus.In || d.LocStatus == (int)EnumLocStatus.Out).Count();

            zoneList.Add(new Zone()
            {
                ZoneName = zoneName,
                TotalCapacity = zoneLocs.Count,
                UsedShelfCount = usedCount,
                EmptyShelfCount = emptyCount,
                BlockedEmptyShelfCount = blockCount,
                ReserveShelfCount = reserveCount,
            });


            var body = new InventoryZoneDataReportMessageBody(zoneLocs.FirstOrDefault().Aisle, zoneList);
            _mesCommunicateService.InventoryZoneDataRequest(new InventoryZoneDataReportMessage(body));
        }

        public void InventoryPallet(string zoneName)
        {
            var pallets = _wcsDbContext.WcsLocations
                                    .AsNoTracking()
                                    .Where(x => x.LocType == "shelf")
                                    .Where(x => x.ZoneName == zoneName)
                                    .Where(x => !string.IsNullOrEmpty(x.UnitId))
                                    .Select(x => new Pallet()
                                    {
                                        PalletName = x.UnitId,
                                        CurrentPositionName = x.WcsLocName,
                                        CurrentPositionType = "SHELF",
                                        PalletLocState = (x.IsLock || x.SrmOccupyFlag) ? "BLOCKED" : "UNBLOCKED",
                                        CurrentZoneName = x.ZoneName,
                                        TransferState = "INSTK"
                                    })
                                    .ToList();



            _mesCommunicateService.InventoryPalletDataRequest(new InventoryPalletDataReportMessage(new InventoryPalletDataReportMessageBody(zoneName.Substring(0, 8), pallets)));
        }


        public void InventoryPallet(List<string> zoneNames)
        {
            foreach (var zoneName in zoneNames)
            {
                InventoryPallet(zoneName);
            }
        }
        public MachineAddressDto GetAddress(string unitId)
        {
            var loc = GetPalletLocation(unitId);

            if (loc != null)
            {
                return new MachineAddressDto()
                {
                    MachineName = loc.Aisle,
                    PositionName = loc.WcsLocName,
                    PositionType = "SHELF",
                    ZoneName = loc.ZoneName
                };
            }

            var con = _asrs.Pcons.FirstOrDefault(x => x.UnitId == unitId);

            if (con != null)
            {
                return new MachineAddressDto()
                {
                    MachineName = con.MachineName,
                    PositionName = con.PortName,
                    PositionType = "PORT",
                    ZoneName = ""
                };
            }

            var srm = _asrs.Srms.FirstOrDefault(x => x.UnitId == unitId);
            if (srm != null)
            {
                return new MachineAddressDto()
                {
                    MachineName = srm.MachineName,
                    PositionName = srm.PortName,
                    PositionType = "PORT",
                    ZoneName = ""
                };
            }

            return new MachineAddressDto();
        }
        public MachineAddressDto GetLocAddress(string locName)
        {
            var loc = _wcsDbContext.WcsLocations
                                 .AsQueryable()
                                 .Where(x => x.LocType == "shelf")
                                 .Where(d => d.WcsLocName == locName)
                                 .FirstOrDefault();

            if (loc != null)
            {
                return new MachineAddressDto()
                {
                    MachineName = loc.Aisle,
                    PositionName = loc.WcsLocName,
                    PositionType = "SHELF",
                    ZoneName = loc.ZoneName
                };
            }

            return new MachineAddressDto();
        }
        public CurrentPalletModel SearchPallet(string unitId)
        {
            try
            {
                var palletModel = new CurrentPalletModel();
                var addr = GetAddress(unitId);

                var task = _wcsDbContext.MainTasks
                    .AsNoTracking()
                    .Where(x => x.UnitId == unitId)
                    .FirstOrDefault();

                palletModel.CurrentLocation = addr;
                palletModel.CurrentTask = task;
                return palletModel;
            }
            catch (Exception ex)
            {
                _logger.AddSystemErrorLog($"LocationService->SearchPallet:{ex.Message}");
                throw new WarningException($"查找{unitId}时发生未知异常");
            }

        }
    }



    public class TempHandOffBay
    {
        public int LeftBay { get; set; }
        public int RightBay { get; set; }
    }
}
